#ifndef __EXCEPTIONS_H__
  #define __EXCEPTIONS_H__

#include <string>

using namespace std;

// exception types
enum exception_type {
  INDEX_EXCEPTION = 0,
  DB_EXCEPTION,
  PARAMETER_EXCEPTION,
  SQL_INJECTION_EXCEPTION,
  POINTER_EXCEPTION,
  FILE_EXCEPTION,
  NOT_ENOUGH_INFO_EXCEPTION,
  OPERATION_NOT_ALLOWED_EXCEPTION,
  SOCKET_EXCEPTION,
  INI_PARSER_EXCEPTION,
  XML_PARSER_EXCEPTION,
  NOT_SUPPORTED_EXCEPTION,
  THREAD_EXCEPTION
};

// defines (required to save file_name & line of each exception)
#define index_exception(a)                 general_exception(__FILE__, __LINE__, a, INDEX_EXCEPTION)
#define db_exception(a)                    general_exception(__FILE__, __LINE__, a, DB_EXCEPTION)
#define parameter_exception(a)             general_exception(__FILE__, __LINE__, a, PARAMETER_EXCEPTION)
#define sql_injection_exception(a)         general_exception(__FILE__, __LINE__, a, SQL_INJECTION_EXCEPTION)
#define pointer_exception(a)               general_exception(__FILE__, __LINE__, a, POINTER_EXCEPTION)
#define file_exception(a)                  general_exception(__FILE__, __LINE__, a, FILE_EXCEPTION)
#define not_enough_info_exception(a)       general_exception(__FILE__, __LINE__, a, NOT_ENOUGH_INFO_EXCEPTION)
#define operation_not_allowed_exception(a) general_exception(__FILE__, __LINE__, a, OPERATION_NOT_ALLOWED_EXCEPTION)
#define socket_exception(a)                general_exception(__FILE__, __LINE__, a, SOCKET_EXCEPTION)
#define ini_exception(a)                   general_exception(__FILE__, __LINE__, a, INI_PARSER_EXCEPTION)
#define xml_exception(a)                   general_exception(__FILE__, __LINE__, a, XML_PARSER_EXCEPTION)
#define not_supported_exception(a)         general_exception(__FILE__, __LINE__, a, NOT_SUPPORTED_EXCEPTION)
#define thread_exception(a)                general_exception(__FILE__, __LINE__, a, THREAD_EXCEPTION)

//////////////////////////////////////////////////////////////////////////////

//! Base class for all kinds of exceptions

/*!
This is the base class for any exceptions.

Implementation date: 2008

Usage:

\code
try {
  ...
} catch (const general_exception &ge) {
  cerr << ge.get_message() << endl;
  cerr << ge.info() << endl;
}
\endcode
*/

class general_exception {
protected:
  string info;
  const char * const file_name;
  unsigned int line;
  exception_type type;

  static bool logging_activated;

public:
  static void activate_exception_logging(bool b);

  //! returns the exception message
  virtual const char *get_message() const;

  //! returns the filename that caused the exception
  virtual const char *get_file_name() const;

  //! returns the line that caused the exception
  virtual unsigned int get_line() const;

  //! returns the exception information
  virtual const string &get_info() const;

  //! returns the type of the exception
  virtual exception_type get_type() const;

  //! constructor
  general_exception(const char *file_name, unsigned int line, const string &info, exception_type type);

  //! destructor
  virtual ~general_exception();
}; // class general_exception

#endif
